package com.factory.web.validation;

import com.factory.web.service.problems.ProblemEnum;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.DirectedWeightedMultigraph;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author milos
 */
public class InputValidation {

    static final Logger LOG = Logger.getLogger(InputValidation.class.getName());

    public boolean validateFileInput(InputStream inputStream, ProblemEnum algorithmicProblem) {
        LOG.log(Level.INFO, "Client input validation started.");

        if (algorithmicProblem.name().equals("SPANN_TREE")) {
            return validateSpannTree(inputStream);
        }
        if (algorithmicProblem.name().equals("SHORTEST_PATH")) {
//            return validateSPT(inputStream);
            return true;
        }
        if (algorithmicProblem.name().equals("TOPOLOGICAL_ORDER")) {
            return new CyclicDetector().isAcyclic(inputStream);
        }
        //TODO TSP input validation
        return true;

    }

    private boolean validateSPT(InputStream inputStream) {
        try {

            DirectedWeightedMultigraph<String, DefaultWeightedEdge> graph = new DirectedWeightedMultigraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
            DefaultWeightedEdge edge1;


            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));

            String line = in.readLine();
            String pathSource;
            Double cost;

            // line has to contain 1 node (start)
            if (line.split(" ").length != 1) {
                return false;
            } else {
                pathSource = line;
            }
            line = in.readLine();
            //second line has to contain 1 node (start) or edge
            if ((line.split(" ").length != 1) && (line.split(" ").length != 3)) {
                return false;
            }
            line = in.readLine();
            int counter = 0;
            while (line != null) {
                counter++;
                String[] splitedLine = line.split(" ");
                if (splitedLine.length != 3) {
                    return false;
                }
                try {
                    cost = Double.parseDouble(splitedLine[2]);
                } catch (Exception e) {
                    return false;
                }
                graph.addVertex(splitedLine[0]);
                graph.addVertex(splitedLine[1]);
                edge1 = graph.addEdge(splitedLine[0], splitedLine[1]);
                graph.setEdgeWeight(edge1, cost);
                line = in.readLine();
            }

            BellmanFordShortestPathWithNegativeCycleDetector cycleDetector = new BellmanFordShortestPathWithNegativeCycleDetector(graph, pathSource);
            if (cycleDetector.hasNegativeCycle()) {
                return false;
            }

        } catch (Exception ex) {
            return false;
        }

        return true;
    }

    private boolean validateSpannTree(InputStream inputStream) {
        try {

            DirectedWeightedMultigraph<String, DefaultWeightedEdge> graph = new DirectedWeightedMultigraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
            DefaultWeightedEdge edge1;


            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));

            String line = in.readLine();
            String pathSource;
            Double cost;
            boolean hasNegativeCost = false;
            pathSource = line.split(" ")[0];
            int counter = 0;
            while (line != null) {
                counter++;
                String[] splitedLine = line.split(" ");
                if (splitedLine.length != 3) {
                    return false;
                }
                try {
                    cost = Double.parseDouble(splitedLine[2]);
                    if (cost < 0) {
                        hasNegativeCost = true;
                    }

                } catch (Exception e) {
                    return false;
                }
                graph.addVertex(splitedLine[0]);
                graph.addVertex(splitedLine[1]);
                edge1 = graph.addEdge(splitedLine[0], splitedLine[1]);
                graph.setEdgeWeight(edge1, cost);
                line = in.readLine();
            }

            if (hasNegativeCost) {
                BellmanFordShortestPathWithNegativeCycleDetector cycleDetector = new BellmanFordShortestPathWithNegativeCycleDetector(graph, pathSource);
                if (cycleDetector.hasNegativeCycle()) {
                    return false;
                }
            }

        } catch (Exception ex) {
            return false;
        }

        return true;
    }
}
